
package com.hlkj.pay.app.merchant.ext.impl.heepay.handler;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import com.alibaba.fastjson.JSONObject;
import com.aliyun.tea.TeaException;
import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.http.template.OkHttpTemplate;
import com.hlkj.pay.app.merchant.IMerchantAccessAppService;
import com.hlkj.pay.app.merchant.ext.impl.MerchantAccessUploadFile;
import com.hlkj.pay.app.merchant.ext.impl.heepay.constanct.HeePayConstant;
import com.hlkj.pay.app.merchant.ext.impl.heepay.dto.HeePayAppChannelParams;
import com.hlkj.pay.app.merchant.ext.impl.heepay.dto.HeePayConfig;
import com.hlkj.pay.app.merchant.ext.impl.heepay.util.*;
import com.hlkj.pay.app.merchant.ext.impl.hnapay.dto.HnapayAppChannelParams;
import com.hlkj.pay.common.MerchantResultCode;
import com.hlkj.pay.common.PayResultCode;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessAuthDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.service.merchant.IMerchantAccessAuthService;
import com.hlkj.pay.util.DateUtils;
import com.hlkj.pay.util.FileUtils;
import com.hlkj.pay.util.SignUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 汇付 商户进件参数处理
 * 
 * @author HlpayTeam
 * @date 2024/09/26 12:02
 */
@Slf4j
@Service
public class HeePayMerchantCommonParamsHandle {

    @Autowired
    private IMerchantAccessAppService merchantAccessAppService;

    @Autowired
    private IMerchantAccessAuthService merchantAccessAuthService;

    private String accessToken;

    private long tokenExpires;

    @Autowired
    private OkHttpTemplate okHttpTemplate;

    @Value("${spring.profiles.active}")
    private String active;

    //获取aut子商户号
    public MerchantAccessAuthDO randomMchId(String channelCode, PayEnums.PAY_TYPE payType) {
        return merchantAccessAppService.randomMchIdByChannelCode(channelCode,payType);
    }

    //获取aut子商户号
    public MerchantAccessAuthDO getAuthDo(String autCode) {
        return merchantAccessAuthService.queryMerchantAccessAuthByCode(autCode);
    }

    public String subject(String subject) throws UnsupportedEncodingException {
        return URLEncoder.encode(subject, "GBK");
    }

    public HeePayAppChannelParams heePayAppChannelParams(MerchantAppChannelDO merchantAppChannelDO,HeePayConfig heePayConfig) {
        HeePayAppChannelParams heePayAppChannelParams= JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), HeePayAppChannelParams.class);
        if(MerchantEnum.APP_CHANNEL_TYPE.MERCHANT_COMMON.getCode().equals(merchantAppChannelDO.getType())){
            // 将参数修改
            heePayConfig.setAppId(heePayAppChannelParams.getAppId());
            heePayConfig.setAgentId(heePayAppChannelParams.getAgentId());
            heePayConfig.setDesKey(heePayAppChannelParams.getDesKey());
            heePayConfig.setMd5Key(heePayAppChannelParams.getMd5Key());
            heePayConfig.setPublicKey(heePayAppChannelParams.getPublicKey());
            heePayConfig.setPrivateKey(heePayAppChannelParams.getPrivateKey());
        }
        return heePayAppChannelParams;
    }

    public CommonResult<HeePayConfig> heePayConfig(ProviderChannelConfigDO providerChannelConfigDO, boolean test) {
        String paramsConfig = providerChannelConfigDO.getParamsConfig();
        if (StringUtils.isEmpty(paramsConfig)) {
            return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_NOT_EXITS);
        }
        // 配置转换
        HeePayConfig heePayConfig = null;
        try {
            heePayConfig = JsonUtils.parseObject(paramsConfig, HeePayConfig.class);
            return CommonResult.success(heePayConfig);
        }
        catch (Exception e) {
            String format = String.format(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getMsg(), "合利宝");
            return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_NOT_EXITS.getCode(), format);
        }
    }

    /**
     * 通用请求
     * 
     * @param object
     * @param method
     * @return
     * @throws Exception
     */
    public CommonResult<Map<String, String>> commonRequest(Object object, String method, HeePayConfig heePayConfig, boolean test, String notifyUrl) {
        HeePayRequestConfig config = new HeePayRequestConfig();
        config.setMchPrivateKey(heePayConfig.getPrivateKey());
        config.setApp_id(heePayConfig.getAppId());
        config.setHyPublicKey(heePayConfig.getPublicKey());
        config.setPathname("/customer-api/gateway");
        config.setNotify_url(notifyUrl);
        config.setProtocol("https");
        config.setHost("openapi.heepay.com");
        config.setMethod("POST");
        config.setFormat("json");
        config.setCharset("utf-8");
        config.setSign_type("RSA2");
        config.setTimestamp(DateUtils.dateToString(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"));
        config.setVersion("1.0");
        HeePayApiResponse response = null;
        try {
            HeePayRequestClient client = new HeePayRequestClient(config);
            log.info("heePay method:{},请求参数:{}", method, JsonUtils.toJsonString(object));
            response = client.callApi(method, object);
            log.info("heePay 返回参数:{}", JsonUtils.toJsonString(response));
            if (HeePayConstant.SUCCESS.equals(response.getCode())) {
                return CommonResult.success(response.getBiz_content());
            }
            else {
                return CommonResult.error(MerchantResultCode.MERCHANT_ACCESS_FILE_ERROR.getCode(), response.getMsg());
            }
        }
        catch (TeaException e) {
            e.printStackTrace();
            return CommonResult.error(MerchantResultCode.MERCHANT_ACCESS_FILE_ERROR.getCode(), e.getMessage());
        }
        catch (Exception ignored) {
            ignored.printStackTrace();
            return CommonResult.error(MerchantResultCode.MERCHANT_ACCESS_FILE_ERROR.getCode(), ignored.getMessage());
        }
    }

    /**
     * 文件上传
     *
     * @param merchantAccessUploadFile
     * @param heePayConfig
     * @return
     * @throws Exception
     */
    public CommonResult<Map<String, String>> fileUploadRequest(MerchantAccessUploadFile merchantAccessUploadFile, HeePayConfig heePayConfig, boolean test) {
        HeePayRequestConfig config = new HeePayRequestConfig();
        config.setMchPrivateKey(heePayConfig.getPrivateKey());
        config.setApp_id(heePayConfig.getAppId());
        config.setHyPublicKey(heePayConfig.getPublicKey());
        config.setPathname("/customer-api/customer.media.upload");
        config.setProtocol("https");
        config.setHost("openapi.heepay.com");
        config.setMethod("POST");
        config.setFormat("json");
        config.setCharset("utf-8");
        config.setSign_type("RSA2");
        config.setTimestamp(DateUtils.dateToString(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"));
        config.setVersion("1.0");
        HeePayApiResponse response = null;
        try {
            byte[] fileBytes = FileUtils.fileBytes(merchantAccessUploadFile.getFileUrl()); // 获取文件字节流
            HeePayRequestClient client = new HeePayRequestClient(config);
            response = client.uploadApi("customer.media.upload", merchantAccessUploadFile.getFileKey(), merchantAccessUploadFile.getFileUrl(), fileBytes);
            log.info("heePay 文件上传返回参数:{}", JsonUtils.toJsonString(response));

            if (HeePayConstant.SUCCESS.equals(response.getCode())) {
                // Map<String, String> bizContent = response.getBiz_content();
                // merchantAccessUploadFile.setFileId(bizContent.get("file_id"));
                return CommonResult.success(response.getBiz_content());
            }
            else {
                return CommonResult.error(MerchantResultCode.MERCHANT_ACCESS_FILE_ERROR.getCode(), response.getMsg());
            }
        }
        catch (TeaException e) {
            e.printStackTrace();
            // System.out.println("响应数据：code=" + e.getCode() + ",msg=" + e.getMessage());
            return CommonResult.error(MerchantResultCode.MERCHANT_ACCESS_FILE_ERROR.getCode(), e.getMessage());
        }
        catch (Exception ignored) {
            ignored.printStackTrace();
            return CommonResult.error(MerchantResultCode.MERCHANT_ACCESS_FILE_ERROR.getCode(), ignored.getMessage());
        }
    }

    public static String date(String date) {
        if (!StringUtils.hasText(date)) {
            return null;
        }
        return date;
    }

    public static String licenseType(String code) {
        if (!StringUtils.hasText(code)) {
            return null;
        }
        // 营业执照类型：
        // 1：营业执照
        // 2：营业执照(多证合一)
        // 3：事业单位法人证书
        // 4：社会团体法人登记证书
        // 5：民办非企业单位登记证书
        // 6：基金会法人登记证书
        // 7：宗教活动场所登记证
        // 8：其他证书/批文/证明
        // 9：执业许可证/执业证
        // 10：基层群众性自治组织特别法人统一社会信用代码证
        // 11：农村集体经济组织登记证
        // 12：业主委员会备案证明

        // 11 营业执照
        // 12 组织机构代码证
        // 13 税务登记证
        // 14 统一社会信用代码证
        // 15 单位证明
        // 16 事业单位法人正式
        // 17 民办非企业单位登记证书
        // 18 基金会法人登记证书
        // 19 社会团体登记证书
        // 99 其它
        switch (code) {
            case "1":
            case "2":
                return "11";
            case "3":
                return "16";
            case "4":
                return "19";
            case "5":
                return "17";
            case "6":
                return "18";
            case "7":
                return "12";
            case "8":
                return "99";
            case "9":
                return "99";
            case "10":
                return "12";
            case "11":
                return "12";
            case "12":
                return "15";
            default:
                return null;
        }
    }

    public static String certType(String code) {
        if (!StringUtils.hasText(code)) {
            return null;
        }
        // 营业执照类型：
        // 1:身份证
        // 2:护照
        // 3:军官证
        // 4:士兵证
        // 5:回乡证
        // 6:户口本
        // 7:外国护照
        // 8:其他
        // 9:暂住证
        // 10:警官证
        // 11:文职干部证
        // 12:港澳台同胞通行证
        // 13:外国人居留证
        // 14:台胞证
        // 15:港澳台居住证
        // 16：营业执照 （只有部分场景才会用到 如 受益人和股东）

        // 0=未知,1=身份证,2=香港来往大陆通行证,3=澳门来往大陆通行证,4=台湾来往大陆通行证,5=外国公民护照
        switch (code) {
            case "1":
                return "1";
            case "2":
                return "5";
            case "14":
                return "4";
            default:
                return "0";
        }
    }

    public static String fileUrl(boolean test) {
        // 测试环境内网：http://htkactvi-sit.lakala.sh.in/registration/api/registration
        // 测试环境外网：https://test.wsmsd.cn/sit//htkregistration
        // 生产环境：https://htkactvi.lakala.com/registration
        // 1文件上传
        // 请求方式：post
        // 请求接口 /file/upload
        if (test) {
            return "https://test.wsmsd.cn/sit//htkregistration";
        }
        else {
            return "https://htkactvi.lakala.com/registration";
        }
    }

    public CommonResult<String> heePayOrderRequestRsa(String requestUrl, HeePayConfig heePayConfig, Map<String, Object> params) {

        try {
            String sign = SignUtils.signRsa(params, heePayConfig.getPrivateKey(), null);
            params.put("sign", sign);
            String response = okHttpTemplate.post(requestUrl, JsonUtils.toJsonString(params), null);
            return CommonResult.success(response);
        }
        catch (Exception e) {
            e.printStackTrace();
            return CommonResult.error(1, e.getMessage());
        }
    }

    public CommonResult<String> heePayOrderRequest(String requestUrl, HeePayConfig heePayConfig, Map<String, String> params, String fieldConfig) {
        // MD5加密得出签名结果
        String sign = HynetUtil.getMD5(params, fieldConfig, heePayConfig.getMd5Key());
        params.put("sign", sign);
        params.remove("key");
        try {
            log.info("汇付宝请求参数 url:{},params:{}", requestUrl, JsonUtils.toJsonString(params));
            String response = sendPost2(requestUrl, params);
            log.info("汇付宝返回参数 url:{},params:{}", requestUrl, response);
            if (StringUtils.hasText(response)) {
                if (response.startsWith("<!DOCTYPE html>")) {
                    // 使用 Hutool 的 HtmlUtil 来解析 HTML
                    // 解析 HTML
                    Document doc = Jsoup.parse(response);
                    String errMsg = doc.getElementById("errMsg").text();
                    if (StringUtils.hasText(errMsg)) {
                        return CommonResult.error(1, errMsg);
                    }
                    else {
                        return CommonResult.error(1, response);
                    }
                }
                // if (response.startsWith("<!DOCTYPE html>")) {
                // // 使用 Hutool 的 HtmlUtil 来解析 HTML
                // // 解析 HTML
                // Document doc = Jsoup.parse(response);
                // String errMsg = doc.getElementById("errMsg").text();
                // if (StringUtils.hasText(errMsg)) {
                // return CommonResult.error(1, errMsg);
                // }
                // else {
                // return CommonResult.error(1, response);
                // }
                // }
                return CommonResult.success(response);
            }
            else {
                return CommonResult.error(1, "汇付宝接口地址" + requestUrl + ",返回信息为空");
            }
        }
        catch (IOException e) {
            e.printStackTrace();
            return CommonResult.error(1, e.getMessage());
        }

    }

    public CommonResult<String> heePayRefundOrderRequest(String requestUrl, HeePayConfig heePayConfig, Map<String, String> params, String fieldConfig) {
        // MD5加密得出签名结果
        String sign = HynetUtil.getMD5LowerCase(params, fieldConfig, heePayConfig.getMd5Key());
        params.put("sign", sign);
        params.remove("key");
        try {
            log.info("汇付宝请求参数 url:{},params:{}", requestUrl, JsonUtils.toJsonString(params));
            String response = sendPost2(requestUrl, params);
            log.info("汇付宝返回参数 url:{},params:{}", requestUrl, response);
            if (StringUtils.hasText(response)) {
                return CommonResult.success(response);
            }
            else {
                return CommonResult.error(1, "汇付宝接口地址" + requestUrl + ",返回信息为空");
            }
        }
        catch (IOException e) {
            e.printStackTrace();
            return CommonResult.error(1, e.getMessage());
        }

    }

    public CommonResult<String> heePayOrderRequest(String requestUrl, HeePayConfig heePayConfig, Map<String, String> params, String fieldConfig, Set<String> subjectSet) {
        // MD5加密得出签名结果
        String sign = HynetUtil.getMD5(params, fieldConfig, heePayConfig.getMd5Key());
        params.put("sign", sign);
        if (!CollectionUtils.isEmpty(subjectSet)) {
            for (String subject : subjectSet) {
                try {
                    params.put("subject", subject(params.get(subject)));
                }
                catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
        }
        params.remove("key");
        try {
            log.info("汇付宝请求参数 url:{},params:{}", requestUrl, JsonUtils.toJsonString(params));
            String response = sendPost2(requestUrl, params);
            log.info("汇付宝返回参数 url:{},params:{}", requestUrl, response);
            if (StringUtils.hasText(response)) {
                return CommonResult.success(response);
            }
            else {
                return CommonResult.error(1, "汇付宝接口地址" + requestUrl + ",返回信息为空");
            }
        }
        catch (IOException e) {
            e.printStackTrace();
            return CommonResult.error(1, e.getMessage());
        }

    }

    public CommonResult<String> heePayOrderRequest(String requestUrl, HeePayConfig heePayConfig, JSONObject params) {
        try {
            String bizContent = params.getString("biz_content");
            String encryptData = HeePaySignUtil.encrypt(bizContent, heePayConfig.getPublicKey());
            String sign = HeePaySignUtil.sign(JsonUtils.toJsonString(params), heePayConfig.getPrivateKey());

            Map<String, String> param = new HashMap<>();
            param.put("method", params.getString("method"));
            param.put("version", "1.0");
            param.put("merch_id", params.getString("merch_id"));
            param.put("timestamp", params.getString("timestamp"));
            param.put("biz_content", encryptData);
            param.put("sign_type", "RSA1");
            param.put("sign", sign);

            String body = JsonUtils.toJsonString(param);
            log.info("汇付宝请求参数 url:{},params:{}", requestUrl, body);
            String response = sendHttpPost(requestUrl, body);
            log.info("汇付宝返回参数 url:{},params:{}", requestUrl, response);
            if (StringUtils.hasText(response)) {
                return CommonResult.success(response);
            }
            else {
                return CommonResult.error(1, "汇付宝接口地址" + requestUrl + ",返回信息为空");
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            return CommonResult.error(1, e.getMessage());
        }

    }

    /**
     * 发送Post x-www-form-urlencoded请求 response返回为UTF-8
     */
    public static String sendPost2(String url, Map<String, String> parameters) throws IOException {

        String postData = parameters.entrySet().stream().map(entry -> entry.getKey() + "=" + entry.getValue()).collect(Collectors.joining("&"));

        String gbkResponse = "";

        // 创建URL对象
        URL requestUrl = new URL(url);

        // 打开连接
        HttpURLConnection connection = (HttpURLConnection) requestUrl.openConnection();

        // 设置请求方法为POST
        connection.setRequestMethod("POST");

        // 启用输入流和输出流
        connection.setDoInput(true);
        connection.setDoOutput(true);

        // 设置请求头
        connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");

        // 获取输出流并写入请求参数
        try (OutputStream os = connection.getOutputStream()) {
            byte[] input = postData.getBytes(StandardCharsets.UTF_8);
            os.write(input, 0, input.length);
        }

        // 获取HTTP响应码
        int responseCode = connection.getResponseCode();
        // 获取Content-Type头部
        String contentType = connection.getContentType();
        String charset = "GBK"; // 默认使用GBK

        // 如果Content-Type头部指定了charset，使用它
        if (contentType != null && contentType.contains("charset=")) {
            charset = contentType.split("charset=")[1];
        }
        if (responseCode == HttpURLConnection.HTTP_OK) {
            // 获取输入流
            InputStream inputStream = connection.getInputStream();
            // InputStreamReader inputStreamReader = new InputStreamReader(inputStream,
            // "UTF-8");
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, charset);

            BufferedReader reader = new BufferedReader(inputStreamReader);
            String line;
            StringBuilder responseBuilder = new StringBuilder();

            while ((line = reader.readLine()) != null) {
                responseBuilder.append(line);
            }

            // 响应内容
            gbkResponse = responseBuilder.toString();

        }
        else {
            System.out.println("Response entity is empty.");
        }
        return gbkResponse;
    }

    /**
     * 发送Post请求
     *
     * @param httpPost
     * @return
     */
    public String sendHttpPost(String httpUrl, String params) {
        HttpPost httpPost = new HttpPost(httpUrl);// 创建httpPost
        try {
            //设置参数
            StringEntity stringEntity = new StringEntity(params, "UTF-8");
            stringEntity.setContentType("text/json");
            httpPost.setEntity(stringEntity);
        } catch (Exception e) {
            e.printStackTrace();
        }
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        HttpEntity entity = null;
        String responseContent = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();
//            httpPost.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpPost);
            entity = response.getEntity();
            responseContent = EntityUtils.toString(entity, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 关闭连接,释放资源
                if (response != null) {
                    response.close();
                }
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseContent;
    }
}
